﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Collections.ObjectModel;
using ViewMaker.Core.ViewModels;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Input;

namespace ViewMaker.Core.Controls
{
    /// <summary>
    /// リストViewコントロール
    /// </summary>
    public class ListViewControl : HeaderViewControl
    {
        /// <summary>
        /// プロパティ
        /// </summary>
        public new class Properties : HeaderViewControl.Properties
        {
            public const string ItemsSource = "ItemsSource";
            public const string SelectedValuePath = "SelectedValuePath";
            public const string DisplayMemberPath = "DisplayMemberPath";
            public const string SelectionChangedCommand = "SelectionChangedCommand";
        }

        /// <summary>
        /// 一覧用のデータソース
        /// </summary>
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "BindablePathList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        public string ItemsSource
        {
            get { return _itemSource; }
            set
            {
                _itemSource = value;
                OnPropertyChanged("ItemsSource");
                OnPropertyChanged("SelectedValueList");
            }
        }
        private string _itemSource;

        /// <summary>
        /// ItemsSourceで選択されたデータの値を示すプロパティのパス
        /// </summary>
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "SelectedValueList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        public virtual string SelectedValuePath { get; set; }

        /// <summary>
        /// ItemsSourceの各アイテムの表示に利用するプロパティのパス
        /// </summary>
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "SelectedValueList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        public virtual string DisplayMemberPath { get; set; }

        /// <summary>
        /// 一覧用データ（XmlSerializer用）
        /// </summary>
        [Browsable(false)]
        public string[] Items
        {
            get 
            {
                if (ItemsList == null) return null;
                return ItemsList.ToArray(); 
            }
            set
            {
                if (value == null)
                {
                    ItemsList = null;
                    return;
                }
                ItemsList.Clear();
                foreach (string item in value) ItemsList.Add(item);
            }
        }

        /// <summary>
        /// 一覧用データ（バインドではなく直接指定する場合に利用）
        /// </summary>
        [Browsable(false)]
        [XmlIgnore]
        public ObservableCollection<string> ItemsList { get; set; }

        /// <summary>
        /// ItemsList編集コマンドのリンク
        /// </summary>
        [Display(Name = "")]
        [XmlIgnore]
        [View(ViewControlType.Hyperlink)]
        [ViewProperty(HyperlinkViewControl.Properties.Command, "EditItemsCommand")]
        public virtual string EditItemsLink { get { return "Items"; } }

        /// <summary>
        /// ItemsList編集コマンド
        /// </summary>
        [Browsable(false)]
        [XmlIgnore]
        public ICommand EditItemsCommand { get { return CreateCommand(() => ViewUtil.ShowDialog(new StringListEditViewModel(ItemsList))); } }

        /// <summary>
        /// 選択データ変更時に実行するコマンド
        /// </summary>
        [Display(Name = "SelectionChanged", GroupName = CommandGroup)]
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "Item.CommandList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        public string SelectionChangedCommand { get; set; }

        /// <summary>
        /// ItemSourceの子プロパティの一覧
        /// </summary>
        [XmlIgnore]
        [Browsable(false)]
        public ObservableCollection<string> SelectedValueList
        {
            get
            {
                if (ItemsSource == null) return null;
                return this.Item.CreateChildBindablePath(ItemsSource);
            }
        }

        /// <summary>
        /// 選択関連のプロパティを設定する
        /// </summary>
        /// <param name="node"></param>
        protected void BindSelectedItem(XamlNode node)
        {
            if (SelectedValuePath != null)
            {
                SetBindingAttribute(node, "SelectedValue", Item.BindPath, Item.IsOneWay);
                node.SetAttribute("SelectedValuePath", SelectedValuePath);
            }
            else
            {
                SetBindingAttribute(node, "SelectedItem", Item.BindPath, Item.IsOneWay);
            }
            if (DisplayMemberPath != null) node.SetAttribute("DisplayMemberPath", DisplayMemberPath);
        }

        #region ShouldSerialize

        public virtual bool ShouldSerializeItems() { return Items != null && Items.Count() > 0; }

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public ListViewControl()
        {
            ItemsList = new ObservableCollection<string>();
        }


        /// <summary>
        /// プロパティをコピーする
        /// </summary>
        /// <param name="source"></param>
        internal override void CopyFrom(ViewElement source)
        {
            base.CopyFrom(source);
            var header = source as ListViewControl;
            if (header != null)
            {
                this.ItemsSource = header.ItemsSource;
                this.SelectedValuePath = header.SelectedValuePath;
                this.DisplayMemberPath = header.DisplayMemberPath;
                this.Items = header.Items;

            }

        }
    }

}
